/**
 * Raft log implementation
 */

#include <xdevice/raft.h>
#include <xdevice/storage.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/* 日志条目结构 */
typedef struct raft_log_entry {
    uint64_t index;
    uint64_t term;
    size_t data_size;
    void* data;
    struct raft_log_entry* next;
} raft_log_entry_t;

/* 日志管理结构 */
typedef struct {
    raft_log_entry_t* entries;
    uint64_t last_index;
    uint64_t commit_index;
    xdevice_storage_backend_t* storage;  // 存储后端
    char log_device_name[XDEVICE_MAX_DEVICE_NAME];  // 日志设备名
    pthread_mutex_t lock;
    bool initialized;
    bool persistent_mode;  // 是否启用持久化模式
} raft_log_t;

static raft_log_t g_log = {0};

/* 全局统计信息 */
static raft_stats_t g_raft_stats = {0};
static pthread_mutex_t g_stats_lock = PTHREAD_MUTEX_INITIALIZER;

/* 静态函数声明 */
static int raft_log_recover_from_storage(void);
static int raft_log_persist_entry(raft_log_entry_t* entry);
static void update_log_stats(void);

int raft_log_init(void) {
    return raft_log_init_with_storage(NULL, NULL);
}

int raft_log_init_with_storage(xdevice_storage_backend_t* storage, const char* log_device_name) {
    if (g_log.initialized) {
        return 0;
    }
    
    if (pthread_mutex_init(&g_log.lock, NULL) != 0) {
        return -1;
    }
    
    g_log.entries = NULL;
    g_log.last_index = 0;
    g_log.commit_index = 0;
    g_log.storage = storage;
    g_log.persistent_mode = (storage != NULL);
    
    if (g_log.persistent_mode && log_device_name) {
        strncpy(g_log.log_device_name, log_device_name, sizeof(g_log.log_device_name) - 1);
        g_log.log_device_name[sizeof(g_log.log_device_name) - 1] = '\0';
        
        // 尝试从存储后端恢复日志
        printf("[Raft Log] 启用持久化模式，日志设备: %s\n", log_device_name);
        
        // 打开日志设备
        if (storage->ops->open_device(storage, log_device_name) == 0) {
            printf("[Raft Log] 日志设备已存在，尝试恢复日志...\n");
            // TODO: 实现日志恢复逻辑
            if (raft_log_recover_from_storage() == 0) {
                printf("[Raft Log] 日志恢复成功，最后索引: %lu\n", g_log.last_index);
            } else {
                printf("[Raft Log] 日志恢复失败，从空日志开始\n");
            }
        } else {
            printf("[Raft Log] 日志设备不存在，创建新的日志设备\n");
            if (storage->ops->create_device(storage, log_device_name, 1024*1024*64) == 0) { // 64MB
                printf("[Raft Log] 日志设备创建成功\n");
            } else {
                printf("[Raft Log] 日志设备创建失败\n");
                g_log.persistent_mode = false;
            }
        }
    }
    
    g_log.initialized = true;
    return 0;
}

/* 日志持久化恢复函数 */
static int raft_log_recover_from_storage(void) {
    if (!g_log.storage || !g_log.persistent_mode) {
        return -1;
    }
    
    // 简单的日志恢复实现
    // 读取日志头部，包含日志条目数量
    uint64_t entry_count = 0;
    int64_t bytes_read = g_log.storage->ops->read(
        g_log.storage, g_log.log_device_name, 0, 
        &entry_count, sizeof(entry_count)
    );
    
    if (bytes_read != sizeof(entry_count)) {
        printf("[Raft Log] 无法读取日志头部\n");
        return -1;
    }
    
    printf("[Raft Log] 发现 %lu 个日志条目需要恢复\n", entry_count);
    
    if (entry_count == 0) {
        g_log.last_index = 0;
        return 0;
    }
    
    // 简化版本：这里只恢复基本计数，实际项目中需要恢复所有条目
    g_log.last_index = entry_count;
    g_log.commit_index = entry_count; // 假设所有日志都已提交
    
    return 0;
}

/* 将日志条目持久化到存储 */
static int raft_log_persist_entry(raft_log_entry_t* entry) {
    if (!g_log.storage || !g_log.persistent_mode || !entry) {
        return 0; // 非持久化模式，直接返回成功
    }
    
    // 简单的持久化实现：更新条目计数
    uint64_t new_count = g_log.last_index;
    int64_t bytes_written = g_log.storage->ops->write(
        g_log.storage, g_log.log_device_name, 0,
        &new_count, sizeof(new_count)
    );
    
    if (bytes_written != sizeof(new_count)) {
        printf("[Raft Log] 日志持久化失败\n");
        return -1;
    }
    
    // 同步到磁盘
    g_log.storage->ops->sync(g_log.storage, g_log.log_device_name);
    
    return 0;
}

void raft_log_cleanup(void) {
    if (!g_log.initialized) {
        return;
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    raft_log_entry_t* current = g_log.entries;
    while (current) {
        raft_log_entry_t* next = current->next;
        if (current->data) {
            free(current->data);
        }
        free(current);
        current = next;
    }
    
    g_log.entries = NULL;
    g_log.initialized = false;
    
    pthread_mutex_unlock(&g_log.lock);
    pthread_mutex_destroy(&g_log.lock);
}

int raft_log_append(uint64_t term, const void* data, size_t size) {
    if (!g_log.initialized || !data || size == 0) {
        return -1;
    }
    
    raft_log_entry_t* entry = malloc(sizeof(raft_log_entry_t));
    if (!entry) {
        return -1;
    }
    
    entry->data = malloc(size);
    if (!entry->data) {
        free(entry);
        return -1;
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    entry->index = ++g_log.last_index;
    entry->term = term;
    entry->data_size = size;
    memcpy(entry->data, data, size);
    entry->next = g_log.entries;
    g_log.entries = entry;
    
    // 持久化新条目
    if (raft_log_persist_entry(entry) != 0) {
        printf("[Raft Log] 警告: 日志条目持久化失败\n");
    }
    
    // 更新统计信息
    update_log_stats();
    
    pthread_mutex_unlock(&g_log.lock);
    
    return 0;
}

int raft_log_get_entry(uint64_t index, void* data, size_t* size, uint64_t* term) {
    if (!g_log.initialized || !data || !size) {
        return -1;
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    raft_log_entry_t* current = g_log.entries;
    while (current) {
        if (current->index == index) {
            if (*size < current->data_size) {
                pthread_mutex_unlock(&g_log.lock);
                return -1; // Buffer too small
            }
            
            memcpy(data, current->data, current->data_size);
            *size = current->data_size;
            if (term) {
                *term = current->term;
            }
            
            pthread_mutex_unlock(&g_log.lock);
            return 0;
        }
        current = current->next;
    }
    
    pthread_mutex_unlock(&g_log.lock);
    return -1; // Entry not found
}

uint64_t raft_log_get_last_index(void) {
    if (!g_log.initialized) {
        return 0;
    }
    
    pthread_mutex_lock(&g_log.lock);
    uint64_t index = g_log.last_index;
    pthread_mutex_unlock(&g_log.lock);
    
    return index;
}

uint64_t raft_log_get_last_term(void) {
    if (!g_log.initialized || !g_log.entries) {
        return 0;
    }
    
    pthread_mutex_lock(&g_log.lock);
    uint64_t term = g_log.entries->term;
    pthread_mutex_unlock(&g_log.lock);
    
    return term;
}

/* ========== 日志复制和一致性功能 ========== */

/* 获取提交索引 */
uint64_t raft_log_get_commit_index(void) {
    if (!g_log.initialized) {
        return 0;
    }
    
    pthread_mutex_lock(&g_log.lock);
    uint64_t commit = g_log.commit_index;
    pthread_mutex_unlock(&g_log.lock);
    
    return commit;
}

/* 设置提交索引 */
int raft_log_set_commit_index(uint64_t commit_index) {
    if (!g_log.initialized) {
        return -1;
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    if (commit_index > g_log.last_index) {
        pthread_mutex_unlock(&g_log.lock);
        return -1;  // 不能提交未存在的日志
    }
    
    if (commit_index > g_log.commit_index) {
        g_log.commit_index = commit_index;
        printf("[RaftLog] 提交索引更新到 %lu\n", commit_index);
        
        // 更新统计信息
        pthread_mutex_lock(&g_stats_lock);
        g_raft_stats.bytes_replicated += (commit_index - g_raft_stats.committed_entries) * 4096; // 假设平均4KB
        pthread_mutex_unlock(&g_stats_lock);
        update_log_stats();
    }
    
    pthread_mutex_unlock(&g_log.lock);
    
    return 0;
}

/* 检查日志一致性 */
bool raft_log_check_consistency(uint64_t prev_index, uint64_t prev_term) {
    if (!g_log.initialized) {
        return false;
    }
    
    if (prev_index == 0) {
        return true;  // 空日志总是一致的
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    raft_log_entry_t* current = g_log.entries;
    while (current) {
        if (current->index == prev_index) {
            bool consistent = (current->term == prev_term);
            pthread_mutex_unlock(&g_log.lock);
            return consistent;
        }
        current = current->next;
    }
    
    pthread_mutex_unlock(&g_log.lock);
    return false;  // 找不到对应索引的日志条目
}

int raft_log_commit_to(uint64_t commit_index) {
    if (!g_log.initialized) {
        return -1;
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    if (commit_index <= g_log.commit_index) {
        pthread_mutex_unlock(&g_log.lock);
        return 0; // 已经提交过了
    }
    
    if (commit_index > g_log.last_index) {
        commit_index = g_log.last_index; // 不能提交超过最后索引的条目
    }
    
    printf("[Raft Log] 提交日志到索引: %lu (原提交索引: %lu)\n", 
           commit_index, g_log.commit_index);
    
    // 更新提交索引
    uint64_t old_commit_index = g_log.commit_index;
    g_log.commit_index = commit_index;
    
    // 更新统计信息
    pthread_mutex_lock(&g_stats_lock);
    g_raft_stats.committed_entries = g_log.commit_index;
    g_raft_stats.pending_entries = g_log.last_index - g_log.commit_index;
    g_raft_stats.bytes_replicated += (commit_index - old_commit_index) * 4096; // 假设平均4KB
    pthread_mutex_unlock(&g_stats_lock);
    
    pthread_mutex_unlock(&g_log.lock);
    
    return 0;
}

/* 截断日志（从指定索引开始删除） */
int raft_log_truncate_from(uint64_t start_index) {
    if (!g_log.initialized) {
        return -1;
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    raft_log_entry_t* current = g_log.entries;
    raft_log_entry_t* prev = NULL;
    
    while (current) {
        if (current->index >= start_index) {
            // 删除从这个索引开始的所有条目
            if (prev) {
                prev->next = NULL;
            } else {
                g_log.entries = NULL;
            }
            
            // 释放被删除的条目
            while (current) {
                raft_log_entry_t* to_delete = current;
                current = current->next;
                free(to_delete->data);
                free(to_delete);
            }
            
            // 更新最后索引
            if (prev) {
                g_log.last_index = prev->index;
            } else {
                g_log.last_index = 0;
            }
            
            printf("[RaftLog] 截断日志从索引 %lu，新的最后索引: %lu\n", 
                   start_index, g_log.last_index);
            break;
        }
        
        prev = current;
        current = current->next;
    }
    
    pthread_mutex_unlock(&g_log.lock);
    
    return 0;
}

/* 批量追加日志条目 */
int raft_log_append_entries(raft_log_entry_t* entries, int count) {
    if (!g_log.initialized || !entries || count <= 0) {
        return -1;
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    for (int i = 0; i < count; i++) {
        raft_log_entry_t* new_entry = malloc(sizeof(raft_log_entry_t));
        if (!new_entry) {
            pthread_mutex_unlock(&g_log.lock);
            return -1;
        }
        
        new_entry->index = ++g_log.last_index;
        new_entry->term = entries[i].term;
        new_entry->data_size = entries[i].data_size;
        
        new_entry->data = malloc(entries[i].data_size);
        if (!new_entry->data) {
            free(new_entry);
            pthread_mutex_unlock(&g_log.lock);
            return -1;
        }
        
        memcpy(new_entry->data, entries[i].data, entries[i].data_size);
        
        // 插入到链表头部
        new_entry->next = g_log.entries;
        g_log.entries = new_entry;
        
        printf("[RaftLog] 追加日志条目，索引: %lu, 任期: %lu, 大小: %zu\n",
               new_entry->index, new_entry->term, new_entry->data_size);
    }
    
    pthread_mutex_unlock(&g_log.lock);
    
    return 0;
}

/* 获取指定范围的日志条目 */
int raft_log_get_entries_range(uint64_t start_index, uint64_t end_index, 
                               raft_log_entry_t** entries, int* count) {
    if (!g_log.initialized || !entries || !count) {
        return -1;
    }
    
    pthread_mutex_lock(&g_log.lock);
    
    *count = 0;
    raft_log_entry_t* current = g_log.entries;
    
    // 先计算范围内的条目数量
    while (current) {
        if (current->index >= start_index && current->index <= end_index) {
            (*count)++;
        }
        current = current->next;
    }
    
    if (*count == 0) {
        pthread_mutex_unlock(&g_log.lock);
        return 0;
    }
    
    // 分配结果数组
    *entries = malloc(sizeof(raft_log_entry_t) * (*count));
    if (!*entries) {
        pthread_mutex_unlock(&g_log.lock);
        return -1;
    }
    
    // 复制条目数据
    current = g_log.entries;
    int index = 0;
    
    while (current && index < *count) {
        if (current->index >= start_index && current->index <= end_index) {
            (*entries)[index] = *current;
            
            // 复制数据
            (*entries)[index].data = malloc(current->data_size);
            if ((*entries)[index].data) {
                memcpy((*entries)[index].data, current->data, current->data_size);
            }
            
            index++;
        }
        current = current->next;
    }
    
    pthread_mutex_unlock(&g_log.lock);
    
    return 0;
}

/* 更新统计信息的辅助函数 */
static void update_log_stats(void) {
    pthread_mutex_lock(&g_stats_lock);
    g_raft_stats.last_log_index = g_log.last_index;
    g_raft_stats.commit_index = g_log.commit_index;
    g_raft_stats.pending_entries = g_log.last_index - g_log.commit_index;
    
    // 计算总条目数
    g_raft_stats.total_log_entries = g_log.last_index;
    g_raft_stats.committed_entries = g_log.commit_index;
    pthread_mutex_unlock(&g_stats_lock);
}

/* 统计接口实现 */
int raft_get_stats(raft_stats_t* stats) {
    if (!stats) {
        return -1;
    }
    
    pthread_mutex_lock(&g_stats_lock);
    // 更新最新统计信息
    if (g_log.initialized) {
        g_raft_stats.last_log_index = g_log.last_index;
        g_raft_stats.commit_index = g_log.commit_index;
        g_raft_stats.pending_entries = g_log.last_index - g_log.commit_index;
        g_raft_stats.total_log_entries = g_log.last_index;
        g_raft_stats.committed_entries = g_log.commit_index;
    }
    
    *stats = g_raft_stats;
    pthread_mutex_unlock(&g_stats_lock);
    
    return 0;
}

int raft_get_node_stats(int node_id, raft_stats_t* stats) {
    (void)node_id; // Parameter reserved for future multi-node support
    if (!stats) {
        return -1;
    }
    
    // Simple implementation: return current node statistics
    return raft_get_stats(stats);
}

void raft_reset_stats(void) {
    pthread_mutex_lock(&g_stats_lock);
    memset(&g_raft_stats, 0, sizeof(g_raft_stats));
    pthread_mutex_unlock(&g_stats_lock);
}

int raft_get_replication_status(int node_id, bool* is_replicating) {
    (void)node_id; // Parameter reserved for future multi-node support
    if (!is_replicating) {
        return -1;
    }
    
    // Simple implementation: if there are pending entries, consider replicating
    pthread_mutex_lock(&g_stats_lock);
    *is_replicating = (g_raft_stats.pending_entries > 0);
    pthread_mutex_unlock(&g_stats_lock);
    
    return 0;
}
